package os;

import java.util.LinkedList;

/**
 * Equivalent to a binary semaphore implemented in MiniOS. You can add or change
 * anything except the prototypes of the constructor, P and V methods.
 * 
 * @author Ahmed El-Eryan
 */
public class MiniMutex
{

	// XXX: Implement the MiniMutex class

	/**
	 * Value of the semaphore.
	 */
	private int waitingCounter;
	private int c;
	private MiniMonitor monitor;

	/**
	 * The waiting threads for the critical section.
	 */
	private LinkedList<Thread> queue;
	
	/**
	 * Constructor to MiniMutex class.
	 * 
	 * @param c initial value of the semaphore.
	 */
	public MiniMutex(int c)
	{
		this.waitingCounter = 0;
		this.c = c;
		this.queue = new LinkedList<Thread>();
		this.monitor = new MiniMonitor();
	}

	/**
	 * <b>UnImplemented</b>: Wait function of the semaphore.
	 */
	public synchronized void P()
	{
//		System.out.println("Thread no "+Thread.currentThread().getId()+" begin P");
		monitor.enter();
//		queue.addLast(Thread.currentThread());
		if(c == 1){
//			System.out.println("Thread no "+Thread.currentThread().getId()+" found binary true and enters");
		}
		else{
			try
			{
				waitingCounter++;
				while( c == 0 )
				{
					monitor.leave();
//					System.out.println("Thread no "+Thread.currentThread().getId()+" will wait for signal in P");
					wait();
					monitor.enter();
//					System.out.println(queue.getFirst().getId());
				}
//				System.out.println("Thread no "+Thread.currentThread().getId()+" is signaled and will continue");
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
		c = 0;
		monitor.leave();
	}

	/**
	 * <b>UnImplemented</b>: Signal function of the semaphore.
	 */
	public synchronized void V()
	{
//		System.out.println("Thread no "+Thread.currentThread().getId()+" begin V");
		monitor.enter();
		c = 1;
		if (waitingCounter == 0)
		{
//			System.out.println("Thread no "+Thread.currentThread().getId()+" found binary false and set it true");
		}
		else
		{
//			if(queue.getFirst() == Thread.currentThread())
//				queue.removeFirst();
			waitingCounter--;
//			System.out.println("Thread no "+Thread.currentThread().getId()+" signals one of the threads");
			notifyAll();
		}
		monitor.leave();
	}
}
